package com.hengyue.system.service.impl;

import com.hengyue.common.constants.CacheConstants;
import com.hengyue.common.constants.UserConstants;
import com.hengyue.common.utils.StringUtils;
import com.hengyue.core.redis.RedisCache;
import com.hengyue.core.text.Convert;
import com.hengyue.exception.ServiceException;
import com.hengyue.system.domain.entity.SysConfig;
import com.hengyue.system.repository.SysConfigRepository;
import com.hengyue.system.service.ISysConfigService;
import jakarta.annotation.PostConstruct;
import jakarta.persistence.criteria.Predicate;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;


@Service
@RequiredArgsConstructor
public class SysConfigServiceImpl implements ISysConfigService {

    @Autowired
    private final SysConfigRepository sysConfigRepository;

    @Autowired
    private RedisCache redisCache;

    /**
     * 项目启动时，初始化参数到缓存
     */
    @PostConstruct
    public void init() {
        loadingConfigCache();
    }


    @Override
    public SysConfig selectConfigById(Long configId) {
        return sysConfigRepository.findById(configId).orElse(null);
    }

    @Override
    public String selectConfigByKey(String configKey) {
        String configValue = Convert.toStr(redisCache.getCacheObject(getCacheKey(configKey)));
        if (StringUtils.isNotEmpty(configValue)) {
            return configValue;
        }
        SysConfig sysConfig = sysConfigRepository.findByConfigKey(configKey).orElse(null);
        if (StringUtils.isNotNull(sysConfig)) {
            redisCache.setCacheObject(getCacheKey(configKey), sysConfig.getConfigValue());
            return sysConfig.getConfigValue();
        }
        return StringUtils.EMPTY;
    }

    /**
     * 获取验证码开关
     *
     * @return true开启，false关闭
     */
    @Override
    public boolean selectCaptchaEnabled() {
        return sysConfigRepository.findByConfigKey("sys.account.captchaEnabled")
                .map(SysConfig::getConfigValue)
                .map(Convert::toBool)
                .orElse(false);
    }

    @Override
    public Page<SysConfig> selectConfigList(SysConfig config, Pageable pageable) {
        return sysConfigRepository.findAll((root, query, cb) -> {
            List<Predicate> predicates = new ArrayList<>();

            // 配置名称模糊查询
            if (StringUtils.isNotEmpty(config.getName())) {
                predicates.add(cb.like(root.get("name"), "%" + config.getName() + "%"));
            }

            // 配置类型精确查询
            if (StringUtils.isNotEmpty(config.getConfigType())) {
                predicates.add(cb.equal(root.get("configType"), config.getConfigType()));
            }

            // 配置键模糊查询
            if (StringUtils.isNotEmpty(config.getConfigKey())) {
                predicates.add(cb.like(root.get("configKey"), "%" + config.getConfigKey() + "%"));
            }

            return query.where(predicates.toArray(new Predicate[0])).getRestriction();
        }, pageable);
    }

    @Override
    public void insertConfig(SysConfig config) {
        sysConfigRepository.save(config);
        redisCache.setCacheObject(getCacheKey(config.getConfigKey()), config.getConfigValue());
    }

    @Override
    public int updateConfig(SysConfig config) {
        return sysConfigRepository.findById(config.getId())
                .map(temp -> {
                    // 如果配置键有变化，删除旧缓存
                    if (!StringUtils.equals(temp.getConfigKey(), config.getConfigKey())) {
                        redisCache.deleteObject(getCacheKey(temp.getConfigKey()));
                    }
                    // 保存新配置并更新缓存
                    sysConfigRepository.save(config);
                    redisCache.setCacheObject(getCacheKey(config.getConfigKey()), config.getConfigValue());
                    return 1; // 返回更新成功标志
                })
                .orElse(0); // 返回更新失败标志
    }
/*@Override
public void updateConfig(SysConfig config) {
    sysConfigRepository.findById(config.getId()).ifPresent(temp -> {
        if (!StringUtils.equals(temp.getConfigKey(), config.getConfigKey())) {
            redisCache.deleteObject(getCacheKey(temp.getConfigKey()));
        }
        sysConfigRepository.save(config);
        redisCache.setCacheObject(getCacheKey(config.getConfigKey()), config.getConfigValue());
    });
}*/


    @Override
    public void deleteConfigByIds(Long[] configIds) {
        for (Long configId : configIds) {
            SysConfig config = selectConfigById(configId);
            if (StringUtils.equals(UserConstants.YES, config.getConfigType())) {
                throw new ServiceException(String.format("内置参数【%1$s】不能删除 ", config.getConfigKey()));
            }
            sysConfigRepository.deleteById(configId);
            redisCache.deleteObject(getCacheKey(config.getConfigKey()));
        }
    }

    @Override
    public void loadingConfigCache() {
        List<SysConfig> configsList = sysConfigRepository.findAll();
        for (SysConfig config : configsList) {
            redisCache.setCacheObject(getCacheKey(config.getConfigKey()), config.getConfigValue());
        }
    }

    @Override
    public void clearConfigCache() {
        Collection<String> keys = redisCache.keys(CacheConstants.SYS_CONFIG_KEY + "*");
        redisCache.deleteObject(keys);
    }

    @Override
    public void resetConfigCache() {
        clearConfigCache();
        loadingConfigCache();
    }

    @Override
    public boolean checkConfigKeyUnique(SysConfig config) {
        Long configId = config.getId() == null ? -1L : config.getId();
        // 查询是否存在相同dictType或code的记录（排除当前记录）
        boolean exists = sysConfigRepository.exists((root, query, cb) ->
                cb.and(
                        cb.or(
                                cb.equal(root.get("configKey"), config.getConfigKey()),
                                cb.equal(root.get("code"), config.getCode())
                        ),
                        cb.notEqual(root.get("id"), configId)
                )
        );
        return !exists;
    }


    /**
     * 设置cache key
     *
     * @param configKey 参数键
     * @return 缓存键key
     */
    private String getCacheKey(String configKey) {
        return CacheConstants.SYS_CONFIG_KEY + configKey;
    }

}
